package jiubeirobot.com.robotshop.utils;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.lzy.okhttputils.OkHttpUtils;
import com.lzy.okhttputils.callback.FileCallback;
import com.orhanobut.logger.Logger;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;

import jiubeirobot.com.robotshop.BuildConfig;
import jiubeirobot.com.robotshop.common.core.BaseCallBack;
import jiubeirobot.com.robotshop.common.core.HUDCallBack;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * ==========================
 * 创建人：TheJoker丶豪 on
 * 创建时间：2017/8/18.
 * 创建内容： okhttp  辅助类
 * ==========================
 */
public class OkHttpHelper {

    private static OkHttpHelper okHttpHelper;

    private static OkHttpClient okHttpClient;

    private Handler handler;
    private Gson gson;

    private OkHttpHelper() {
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .writeTimeout(30, TimeUnit.SECONDS)
                .readTimeout(30, TimeUnit.SECONDS)
                .connectTimeout(30, TimeUnit.SECONDS);
        okHttpClient = builder.build();

        gson = new Gson();
        handler = new Handler(Looper.getMainLooper());//获取主线程的Looper对象来构造一个handler
    }

    public static synchronized OkHttpHelper getInstance() {
        if (null == okHttpHelper) {
            okHttpHelper = new OkHttpHelper();
        }
        return okHttpHelper;
    }

    /**
     * get方式联网请求数据
     */
    public void get(Context context, String relativeUrl, JSONObject params, HUDCallBack baseCallBack, Type clz) {
        try {
            Request request = buildRequest(context, getAbsoluteUrl(context, relativeUrl), params, HttpMethodType.GET);
            doRequest(context, request, baseCallBack, clz);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * post方式联网请求数据
     */
    public void post(Context context, String relativeUrl, JSONObject params, HUDCallBack baseCallBack, Type clz) {
        try {
            Request request = buildRequest(context, getAbsoluteUrl(context, relativeUrl), params, HttpMethodType.POST);
            doRequest(context, request, baseCallBack, clz);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * post文件
     *
     * @param context
     * @param relativeUrl
     * @param params
     * @param baseCallBack
     * @param clz
     */
    public void postNoEncrypt(Context context, String relativeUrl, JSONObject params, HUDCallBack baseCallBack, Type clz) {
        try {
            Request request = buildRequestNo(context, getAbsoluteUrl(context, relativeUrl), params, HttpMethodType.POST);
            doRequest(context, request, baseCallBack, clz);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static Request buildRequestNo(Context context, String url, JSONObject params, HttpMethodType httpMethodType) {
//        try {
//
//            Request.Builder builder = new Request.Builder();
//
//            if (httpMethodType == HttpMethodType.GET) {
//                if (!url.endsWith("?")) {
//                    url += "?";
//                }
//                if (null != params) {
//                    Iterator<String> it = params.keys();
//                    while (it.hasNext()) {
//                        String key = it.next();
//                        url += key + "=" + params.getString(key) + "&";
//                    }
//
//                    url = url.substring(0, url.length() - 1);
//                }
//
//                builder.url(url);
//                builder.get();
//                L.i("OkHttp GET url:" + url);
//
//            } else if (httpMethodType == HttpMethodType.POST) {
//                FormBody.Builder formBodyBuilder = new FormBody.Builder();
//                String relativeUrl = "";
//                L.i(params);
//                if (null != params) {
//                    Iterator<String> it = params.keys();
//                    while (it.hasNext()) {
//                        String key = it.next();
//                        formBodyBuilder.add(key, params.getString(key));
//                        relativeUrl += key + "=" + params.getString(key) + "&";
//                    }
//                    relativeUrl = relativeUrl.substring(0, relativeUrl.length() - 1);
//                }
//
//                RequestBody body = formBodyBuilder.build();
//
//                builder.url(url);
//                builder.post(body);
//
//                L.i("OkHttp POST url:" + url);
//                L.i("OkHttp POST url:" + url + "?" + relativeUrl);
//                L.i("\n\n\n\n-------------------------------------------------------------------------------------------------------------------------------");
//                L.i("PRETTYLOGGER url:" + url + "  params:" + params.toString());
//                L.i("-------------------------------------------------------------------------------------------------------------------------------\n\n\n\n");
//            }
//            return builder.build();
//        } catch (JSONException e) {
//            e.printStackTrace();
//        }
        return null;
    }


    private void doRequest(final Context context, Request request, final HUDCallBack baseCallBack, final Type clz) {
        baseCallBack.requestBefore(request);
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(final Call call, final IOException e) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        baseCallBack.onFailure(call, e);
                    }
                });
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                baseCallBack.onResponse(response);
                L.i(response);

                if (response.isSuccessful()) {
                    try {
                        String resStr = response.body().string();
                        L.e("\n\n\nURL：" + response.request().url() + "\n\n\n");
                        L.e("\n\n\nresStr：" + resStr);

                        JSONObject jsonObject = new JSONObject(resStr);

                        if (BuildConfig.DEBUG) {
                            Logger.json(resStr);
                        }

//                        callBackSuccess(response, baseCallBack, gson.fromJson(resStr, clz));


                        if (!jsonObject.getString("code").equals("200")) {
                            callBackFail(context, jsonObject.getString("message"));
                            return;
                        }
                        if ((jsonObject.getJSONObject("data").getString("state")).equals("0")) {
                            callBackSuccess(response, baseCallBack, gson.fromJson(resStr, clz));
                        } else {
                            callBackError(context, response, baseCallBack, jsonObject.getJSONObject("data").getString("msg"));
                        }

                    } catch (JsonSyntaxException e) {
                        L.i(e.toString());
                        callBackError(context, response, baseCallBack, "数据错误");
                    } catch (Exception e) {
                        L.i(e.toString());
                        callBackError(context, response, baseCallBack, "数据错误");
                    }
                } else {
                    callBackError(context, response, baseCallBack, "连接超时");
                }
            }
        });
    }

    /**
     * 根据网络请求方式构建联网请求时所需的request
     *
     * @param httpMethodType 联网请求方式
     * @return 联网所需的request
     */
    private Request buildRequest(Context context, String url, JSONObject params, HttpMethodType httpMethodType) throws Exception {

        HashMap<String, String> param = new HashMap<String, String>();
        if (null == params) {
            params = new JSONObject();
        }
        JSONObject paObject = getPaObject(context, params);
        Iterator<String> it = paObject.keys();
        while (it.hasNext()) {
            String key = it.next().toString();
            param.put(key, DetectTool.chinaToUnicode(paObject.getString(key)));
            param.put(key, paObject.getString(key));
        }

        String result = Text.encrypt(paObject.toString());
        String signature = result.substring(0, 32);
        String message = result.substring(32);

        L.d("signature:" + signature);
        L.d("message:" + message);

        Request.Builder builder = new Request.Builder();

        builder.url(url);

        if (httpMethodType == HttpMethodType.GET) {
            if (null != params) {
                url += "signature" + signature + "message" + message;
            }
            builder.url(url);
            builder.get();
            L.i("OkHttp GET url:" + url);

        } else if (httpMethodType == HttpMethodType.POST) {
            FormBody.Builder encodingBuilder = new FormBody.Builder();
            encodingBuilder.add("message", message);
            RequestBody rbody = encodingBuilder.build();
            builder.header("signature", signature);
            builder.url(url);
            builder.post(rbody);
            L.i(url);
            L.i(Text.decrypt(signature + message).trim());
            L.i("OkHttp POST url:" + url + "signature=" + signature + "message" + message);
        }

        return builder.build();
    }


    private void callBackSuccess(final Response response, final BaseCallBack baseCallBack, final Object object) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                baseCallBack.onSuccess(response, object, baseCallBack.flag);
            }
        });
    }

    private void callBackError(final Context context, final Response response, final BaseCallBack baseCallBack, final String error) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                baseCallBack.onError(response, 900, new Exception(error));
            }
        });
    }

    private void callBackFail(final Context context, final String message) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                TS.showShort(message);
            }
        });
    }


    /**
     * 根据相对路径获取全路径
     * TODO  这里可以修改网络请求的数据URL的拼接
     *
     * @param context     上下文对象
     * @param relativeUrl 相对路径
     * @return
     */
    private static String getAbsoluteUrl(Context context, String relativeUrl) {
        Log.d("print", "getAbsoluteUrl: " + BuildConfig.SERVER_IP);
        return BuildConfig.SERVER_IP + relativeUrl;

    }

    private static JSONObject getPaObject(Context context, JSONObject params) throws JSONException {
        JSONObject allDataObject = new JSONObject();
        Iterator<String> it = params.keys();
        String v = null;
        while (it.hasNext()) {
            String key = it.next().toString();
            allDataObject.put(key, params.getString(key));
            L.i("***************************key：" + key + "    val：" + params.getString(key));
//            if ("v".equals(key)) {
//                v = params.getString(key);
//            }
        }
        String ts = DetectTool.getTS();
        L.i("--------------------------------------时间" + ts);
        return allDataObject;
    }

    /**
     * 下载文件  基本的get请求
     *
     * @param context
     * @param appUrl
     * @param 下载失败
     */
    public void downloadFile(Context context, String appUrl, FileCallback 下载失败) {
        OkHttpUtils.getInstance()
                .get(appUrl)
                .tag(context)
                .connTimeOut(10000)      // 设置当前请求的连接超时时间
                .readTimeOut(10000)      // 设置当前请求的读取超时时间
                .writeTimeOut(10000)     // 设置当前请求的写入超时时间
                .cacheKey("downloadCacheKey")    // 设置当前请求的缓存key,建议每个不同功能的请求设置一个
                .cacheTime(5000)
                .execute(下载失败);

    }

    /**
     * 枚举，联网请求的联网方式
     */
    enum HttpMethodType {
        GET, POST
    }
}
